<script src="../../dist/mini-vue.js"></script>

<!-- DemoGrid component template -->
<script type="text/x-template" id="grid-template">
    <table v-if="filteredData.value.length">
    <thead>
      <tr>
        <th v-for="key in columns"
          @click="sortBy(key)"
          :class="state.sortKey == key ? 'active' : ''">
          {{ capitalize(key) }}
          <span :class="'arrow ' + (state.sortOrders[key] > 0 ? 'asc' : 'dsc')">
          </span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="entry in filteredData.value">
        <td v-for="key in columns">
          {{entry[key]}}
        </td>
      </tr>
    </tbody>
  </table>
  <p v-else>No matches found.</p>
</script>
<!-- DemoGrid component script -->
<script>
  const { reactive, computed, ref } = MiniVue;

  const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);

  const DemoGrid = {
    template: '#grid-template',
    props: ['data', 'columns', 'filterKey'],
    setup(props) {
      const state = reactive({
        sortKey: '',
        sortOrders: props.columns.reduce((o, key) => ((o[key] = 1), o), {}),
      });

      const filteredData = computed(() => {
        let { data, filterKey } = props;
        if (filterKey) {
          filterKey = filterKey.toLowerCase();
          data = data.filter((row) => {
            return Object.keys(row).some((key) => {
              return String(row[key]).toLowerCase().indexOf(filterKey) > -1;
            });
          });
        }
        const { sortKey } = state;
        if (sortKey) {
          const order = state.sortOrders[sortKey];
          data = data.slice().sort((a, b) => {
            a = a[sortKey];
            b = b[sortKey];
            return (a === b ? 0 : a > b ? 1 : -1) * order;
          });
        }
        return data;
      });

      function sortBy(key) {
        state.sortKey = key;
        state.sortOrders[key] *= -1;
      }

      return {
        state,
        filteredData,
        sortBy,
        capitalize,
      };
    },
  };
</script>

<!-- App template (in DOM) -->
<div id="demo">
  <form id="search">
    Search <input name="query" v-model="searchQuery.value" />
  </form>
  <demo-grid
    :data="gridData"
    :columns="gridColumns"
    :filter-key="searchQuery.value"
  >
  </demo-grid>
</div>
<!-- App script -->
<script>
  MiniVue.createApp({
    components: {
      DemoGrid,
    },
    setup() {
      return {
        // 不同于原版，这里需要用ref
        // 可能是因为v-model机制不同，原版修改的是经过props响应化后的响应式对象，
        // 而这里修改的是普通值，因此要显示定义为ref
        searchQuery: ref(''),
        gridColumns: ['name', 'power'],
        gridData: [
          {
            name: 'Chuck Norris',
            power: Infinity,
          },
          {
            name: 'Bruce Lee',
            power: 9000,
          },
          {
            name: 'Jackie Chan',
            power: 7000,
          },
          {
            name: 'Jet Li',
            power: 8000,
          },
        ],
      };
    },
  }).mount('#demo');
</script>

<style>
  body {
    font-family: Helvetica Neue, Arial, sans-serif;
    font-size: 14px;
    color: #444;
  }

  table {
    border: 2px solid #42b983;
    border-radius: 3px;
    background-color: #fff;
  }

  th {
    background-color: #42b983;
    color: rgba(255, 255, 255, 0.66);
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }

  td {
    background-color: #f9f9f9;
  }

  th,
  td {
    min-width: 120px;
    padding: 10px 20px;
  }

  th.active {
    color: #fff;
  }

  th.active .arrow {
    opacity: 1;
  }

  .arrow {
    display: inline-block;
    vertical-align: middle;
    width: 0;
    height: 0;
    margin-left: 5px;
    opacity: 0.66;
  }

  .arrow.asc {
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-bottom: 4px solid #fff;
  }

  .arrow.dsc {
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 4px solid #fff;
  }
</style>
